package sg.edu.nus.iss.vmcs.customer;

import java.util.Observable;

import sg.edu.nus.iss.vmcs.store.Store;
import sg.edu.nus.iss.vmcs.store.StoreItem;
import sg.edu.nus.iss.vmcs.store.StoreObject;
import sg.edu.nus.iss.vmcs.store.DrinksBrand;
import sg.edu.nus.iss.vmcs.system.Fault;
import sg.edu.nus.iss.vmcs.system.FaultObserver;
import sg.edu.nus.iss.vmcs.system.FaultType;
import sg.edu.nus.iss.vmcs.util.Log;
import sg.edu.nus.iss.vmcs.util.VMCSException;

public class DispenseController implements FaultObserver {	
	private TransactionController 	trxCtrl;
	boolean hasFault = false;

	private DispenseController(){
		observeFault(Fault.getInstance());//SelfRegister to the Fault
	}
	
	public DispenseController(TransactionController transaction_controller) {
		this();
		trxCtrl = transaction_controller; 
	}

	public void allowSelection(boolean activeSelect) {
		if (hasFault) activeSelect = false;//Not allow to select if any fault
		trxCtrl.getCustomerPanel().getDrinkSelectionBox().setActive(activeSelect);		
	}
	
	public boolean dispenseDrink(int selected_brand) throws VMCSException{
		boolean success = true;
		
		try {
			trxCtrl.getMainController().getMachineryController().dispenseDrink(selected_brand);
			trxCtrl.getCustomerPanel().setValue_can_collection_box(
					trxCtrl.getStoreController().getStore(Store.DRINK).getStoreItem(selected_brand).getContent().getName() );
		}
		catch (VMCSException ex) {
			success = false;
			throw new VMCSException(
					"DispenseController.dispenseDrink",
					ex.getMessage());
		}
		
		return success;
	}

	public void updateDrinkSelection(int index) {
		StoreItem item = trxCtrl.getStoreController().getStoreItem(Store.DRINK, index);
		int quantity = item.getQuantity();
		StoreObject obj = item.getContent();
		int price = ((DrinksBrand) obj).getCalculatedPrice();
		String name = ((DrinksBrand) obj).getName();
		trxCtrl.getCustomerPanel().getDrinkSelectionBox().update(index, quantity, price, name);
	}
	
	public void updateDrinkPanel() {
		int len = trxCtrl.getMainController().getStoreController().getStoreSize(Store.DRINK);
		for (int i = 0; i < len; i++) {
			updateDrinkSelection(i);
		}
	}
	
	public void resetCan() {		
		trxCtrl.getCustomerPanel().setValue_can_collection_box("NO CAN");
	}

	public void observeFault(Fault fault) {
		fault.addObserver(this);		
	}
	
	public void update(Observable o, Object arg) {
		if (o instanceof Fault){
			Log.LogIt("DispenseController.update");
			hasFault = true;
			FaultType faultType = ((Fault) o).getState();
			Log.LogIt("DispenseController.update(" + faultType + ")");
			switch (faultType) {
			case CoinReceiverFault:
				// Disable the DispenseController
				break;
			case DispenseFault:
				// Disable the DispenseController
				break;
			case NO_FAULT:
				// Enable the DispenseController
				hasFault = false;
				break;
			}

			setActive(!hasFault);
			Log.LogIt("DispenseController.update:setActive(" + !hasFault + ")");
		}
	}

	private void setActive(boolean active) {
		trxCtrl.getCustomerPanel().getDrinkSelectionBox().setActive(active);
	}
	
	/**
	 * Set Error status of Dispenser
	 * 
	 * @param err
	 *     True - Dispenser Has Error 
	 *     False - Dispenser Error was cleared
	 */
	public void setError(boolean err) {
		Fault fault = getFault();
		if (err) {
			fault.setState(FaultType.DispenseFault);
		} else {
			if (fault.getState().compareTo(FaultType.DispenseFault) == 0) {
				// Current Fault is Dispenser Fault. Reset it.
				fault.setState(FaultType.NO_FAULT);
			}
		}
	}

	private Fault getFault() {
		return  Fault.getInstance();
	}
}
